// Copyright (C) 2009 Jesse Jones
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using MmmDoc.Database;
using MmmDoc.Html;
using Mono.Cecil;
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace MmmDoc
{
	/// <summary>This namespace contains the top level classes as well as some utility classes.</summary>
	internal sealed class NamespaceDoc
	{
	}
	
	/// <summary>Main entry point for the executable.</summary>
	internal static class Program
	{
		/// <summary>Main entry point.</summary>
		public static void Main(string[] args)
		{
			Stopwatch timer = Stopwatch.StartNew();
			
			Settings.Parse(args);
			Hunspell.Init(Settings.Language);
			
			DoGenerate();
			
			if (Settings.Verbosity >= 1)
				if (timer.ElapsedMilliseconds > 60*1000)
					Console.WriteLine("finished in {0:0.000} mins", timer.ElapsedMilliseconds/(60*1000.0));
				else
					Console.WriteLine("finished in {0:0.000} secs", timer.ElapsedMilliseconds/1000.0);
		}
		
		/// <summary>A method with (almost) every piece of supported markup.
		///
		/// <para>Tiger, tiger, burning bright
		/// In the forests of the night,
		/// What immortal hand or eye
		/// Could frame thy fearful symmetry?</para>
		/// 
		/// <para>In what distant deeps or skies
		/// Burnt the fire of thine eyes?
		/// On what wings dare he aspire?
		/// What the hand dare seize the fire?</para>
		/// 
		/// <para>And what shoulder and what art
		/// Could twist the sinews of thy heart?
		/// And, when thy heart began to beat,
		/// What dread hand and what dread feet?</para>
		/// 
		/// <para>What the hammer? What the chain?
		/// In what furnace was thy brain?
		/// What the anvil? What dread grasp
		/// Dare its deadly terrors clasp?</para>
		/// </summary>
		/// <permission name = "System.Security.PermissionSet">Everyone can call this method.</permission>
		/// <param name = "x">The left operand.</param>
		/// <param name = "y">The right operand.</param>
		/// <returns>The sum of <paramref name = "x"/> and <paramref name = "y"/>.</returns>
		/// <exception cref = "System.ArgumentException">Thrown if x &lt; 0.</exception>
		/// <exception cref = "System.InvalidOperationException">Thrown if the core melts down.</exception>
		/// <remarks>Used for testing:
		/// <list type = "number">
		/// <item><description>That all the markup is recognized.</description></item>
		/// <item><description>That we generate the right HTML.</description></item>
		/// <item><description>That the application does not fall over and die.</description></item>
		/// </list>
		/// </remarks>
		/// <example>If, for some reason, you wanted to call <c>Testbed</c> you can do like so:
		/// <code>
		/// int x = 100;		// also see <see cref = "Database.FieldMember.Type"/>
		/// int y = x &lt; 200 ? 20 : 30;
		/// int result = Program.Testbed(x, y /*, 
		/// z*/);
		/// Console.WriteLine("all done!");
		/// </code>
		/// </example>
		/// <seealso cref = "Program"/>
		/// <seealso cref = "Database.Definition"/>
		/// <seealso cref = "Main"/>
		/// <seealso cref = "Database.FieldMember.Type"/>
		[LoaderOptimization(LoaderOptimization.SingleDomain)]
		[ObsoleteAttribute("Don't use this method.")]
		[MethodImpl(MethodImplOptions.Synchronized)]
		public static int Testbed(int x, int y)
		{
			return x + y;
		}
		
		#region Private Methods
		private static void DoGenerate()
		{
			var doc = new Document();
			
			// Load the assemblies.
			foreach (string path in Settings.Assemblies)
			{
				if (Settings.Verbosity >= 1)
					Console.WriteLine("loading '{0}'", path);
					
				AssemblyDefinition assembly = AssemblyFactory.GetAssembly(path);
				doc.AddAssembly(assembly);
			}
			
			doc.OnFinishedAdding();
			
			// Parse the xml files.
			foreach (string path in Settings.HelpFiles)
			{
				if (Settings.Verbosity >= 1)
					Console.WriteLine("parsing '{0}'", path);
				
				var parser = new ParseXml();
				parser.Parse(path);
				parser.ResolveHelpDefinitions(doc);
			}
			
			// Generate the documentation.
			if (Settings.Verbosity >= 1)
				Console.WriteLine("generating docs to '{0}'", Settings.OutDir);
			
			var generate = new Generate(doc);
			generate.Write();
		}
		#endregion
	}
}
